\subsubsection{ARM: 8 arguments}

Utilisons de nouveau l'exemple avec 9 arguments de la section précédente: \myref{example_printf8_x64}.

\lstinputlisting[style=customc]{patterns/03_printf/2.c}

\myparagraph{\OptimizingKeilVI: \ARMMode}

\begin{lstlisting}[style=customasmARM]
.text:00000028             main
.text:00000028
.text:00000028             var_18 = -0x18
.text:00000028             var_14 = -0x14
.text:00000028             var_4  = -4
.text:00000028
.text:00000028 04 E0 2D E5  STR    LR, [SP,#var_4]!
.text:0000002C 14 D0 4D E2  SUB    SP, SP, #0x14
.text:00000030 08 30 A0 E3  MOV    R3, #8
.text:00000034 07 20 A0 E3  MOV    R2, #7
.text:00000038 06 10 A0 E3  MOV    R1, #6
.text:0000003C 05 00 A0 E3  MOV    R0, #5
.text:00000040 04 C0 8D E2  ADD    R12, SP, #0x18+var_14
.text:00000044 0F 00 8C E8  STMIA  R12, {R0-R3}
.text:00000048 04 00 A0 E3  MOV    R0, #4
.text:0000004C 00 00 8D E5  STR    R0, [SP,#0x18+var_18]
.text:00000050 03 30 A0 E3  MOV    R3, #3
.text:00000054 02 20 A0 E3  MOV    R2, #2
.text:00000058 01 10 A0 E3  MOV    R1, #1
.text:0000005C 6E 0F 8F E2  ADR    R0, aADBDCDDDEDFDGD ; "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%"...
.text:00000060 BC 18 00 EB  BL     __2printf
.text:00000064 14 D0 8D E2  ADD    SP, SP, #0x14
.text:00000068 04 F0 9D E4  LDR    PC, [SP+4+var_4],#4
\end{lstlisting}

Ce code peut être divisé en plusieurs parties:

\myindex{Prologue de la fonction}
\begin{itemize}
\item Prologue de la fonction:

\myindex{ARM!\Instructions!STR}
La toute première instruction \INS{STR LR, [SP,\#var\_4]!} sauve \ac{LR} sur la pile,
car nous allons utiliser ce registre pour l'appel à \printf.
Le point d'exclamation à la fin indique un \IT{pré-index}.

Cela signifie que \ac{SP} est d'abord décrémenté de 4, et qu'ensuite \ac{LR}
va être sauvé à l'adresse stockée dans \ac{SP}.
C'est similaire à \PUSH en x86.
Lire aussi à ce propos: \myref{ARM_postindex_vs_preindex}.

\myindex{ARM!\Instructions!SUB}
La seconde instruction \INS{SUB SP, SP, \#0x14} décrémente \ac{SP} (le \glslink{stack pointer}{pointeur de pile})
afin d'allouer \GTT{0x14} (20) octets sur la pile.
En effet, nous devons passer 5 valeurs de 32-bit par la pile à la fonction \printf,
et chacune occupe 4 octets, ce qui fait exactement $5*4=20$.
Les 4 autres valeurs de 32-bit sont passées par les registres.

\item Passer 5, 6, 7 et 8 par la pile: ils sont stockés dans les registres \Reg{0},
\Reg{1}, \Reg{2} et \Reg{3} respectivement.\\
Ensuite, l'instruction \INS{ADD R12, SP, \#0x18+var\_14} écrit l'adresse de la pile
où ces 4 variables doivent être stockées dans le registre \Reg{12}.
\myindex{IDA!var\_?}
\IT{var\_14} est une macro d'assemblage, égal à -0x14, créée par \IDA pour afficher
commodément le code accédant à la pile.
Les macros \IT{var\_?} générée par \IDA reflètent les variables locales dans la pile.

Donc, \GTT{SP+4} doit être stocké dans le registre \Reg{12}. \\
\myindex{ARM!\Instructions!STMIA}
L'instruction suivante \INS{STMIA R12, {R0-R3}} écrit le contenu des registres
\Reg{0}-\Reg{3} dans la mémoire pointée par \Reg{12}.
\INS{STMIA} est l'abréviation de \IT{Store Multiple Increment After} (stocker plusieur incrémenter après).
\IT{\q{Increment After}} signifie que \Reg{12} doit être incrémenté de 4 après
l'écriture de chaque valeur d'un registre.

\item Passer 4 par la pile: 4 est stocké dans \Reg{0} et ensuite, cette valeur, avec l'aide de \\
l'instruction \INS{STR R0, [SP,\#0x18+var\_18]} est sauvée dans la pile.
\IT{var\_18} est -0x18, donc l'offset est 0, donc la valeur du registre \Reg{0}
(4) est écrite à l'adresse écrite dans \ac{SP}.

\item Passer 1, 2 et 3 par des registres:
Les valeurs des 3 premiers nombres (a,b,c) (respectivement 1, 2, 3) sont passées
par les registres \Reg{1}, \Reg{2} et \Reg{3} juste avant l'appel de \printf, et
les 5 autres valeurs sont passées par la pile:

\item appel de \printf

\myindex{Épilogue de fonction}
\item Épilogue de fonction:

L'instruction \INS{ADD SP, SP, \#0x14} restaure le pointeur \ac{SP} à sa valeur
précédente, nettoyant ainsi la pile.
Bien sûr, ce qui a été stocké sur la pile y reste, mais sera récrit lors de
l'exécution ultérieure de fonctions.

\myindex{ARM!\Instructions!LDR}
L'instruction \INS{LDR PC, [SP+4+var\_4],\#4} charge la valeur sauvée de \ac{LR}
depuis la pile dans le registre \ac{PC}, provoquant ainsi la sortie de la fonction.
Il n'y a pas de point d'xclamation---effectivement, \ac{PC} est d'abord chargé
depuis l'adresse stockées dans \ac{SP} ($4+var\_4=4+(-4)=0$, donc cette instruction
est analogue à INS{LDR PC, [SP],\#4}), et ensuite \ac{SP} est incrémenté de 4.
Il s'agit de \IT{post-index}\footnote{Lire à ce propos: \myref{ARM_postindex_vs_preindex}.}.
Pourquoi est-ce qu'\IDA affiche l'instruction comme ça?
Parqu'il veut illustrer la disposition de la pile et le fait que \GTT{var\_4} est
alloué pour sauver la valeur de \ac{LR} dans la pile locale.
Cette instruction est quelque peu similaire à \INS{POP PC} en x86\footnote{Il est
impossible de définir la valeur de \GTT{IP/EIP/RIP} en utilisant \POP en x86, mais
de toutes façons, vous avez le droit de faire l'analogie.}.

\end{itemize}

\myparagraph{\OptimizingKeilVI: \ThumbMode}

\begin{lstlisting}[style=customasmARM]
.text:0000001C             printf_main2
.text:0000001C
.text:0000001C             var_18 = -0x18
.text:0000001C             var_14 = -0x14
.text:0000001C             var_8  = -8
.text:0000001C
.text:0000001C 00 B5        PUSH    {LR}
.text:0000001E 08 23        MOVS    R3, #8
.text:00000020 85 B0        SUB     SP, SP, #0x14
.text:00000022 04 93        STR     R3, [SP,#0x18+var_8]
.text:00000024 07 22        MOVS    R2, #7
.text:00000026 06 21        MOVS    R1, #6
.text:00000028 05 20        MOVS    R0, #5
.text:0000002A 01 AB        ADD     R3, SP, #0x18+var_14
.text:0000002C 07 C3        STMIA   R3!, {R0-R2}
.text:0000002E 04 20        MOVS    R0, #4
.text:00000030 00 90        STR     R0, [SP,#0x18+var_18]
.text:00000032 03 23        MOVS    R3, #3
.text:00000034 02 22        MOVS    R2, #2
.text:00000036 01 21        MOVS    R1, #1
.text:00000038 A0 A0        ADR     R0, aADBDCDDDEDFDGD ; "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%"...
.text:0000003A 06 F0 D9 F8  BL      __2printf
.text:0000003E
.text:0000003E             loc_3E   ; CODE XREF: example13_f+16
.text:0000003E 05 B0        ADD     SP, SP, #0x14
.text:00000040 00 BD        POP     {PC}
\end{lstlisting}

La sortie est presque comme dans les exemples précédents. Toutefois, c'est du code
Thumb et les valeurs sont arrangées différemment dans la pile:
8 vient en premier, puis 5, 6, 7 et 4 vient en troisième premier, puis 5, 6, 7 et 4 vient en troisième..

\myparagraph{\OptimizingXcodeIV: \ARMMode}

\begin{lstlisting}[style=customasmARM]
__text:0000290C             _printf_main2
__text:0000290C
__text:0000290C             var_1C = -0x1C
__text:0000290C             var_C  = -0xC
__text:0000290C
__text:0000290C 80 40 2D E9   STMFD  SP!, {R7,LR}
__text:00002910 0D 70 A0 E1   MOV    R7, SP
__text:00002914 14 D0 4D E2   SUB    SP, SP, #0x14
__text:00002918 70 05 01 E3   MOV    R0, #0x1570
__text:0000291C 07 C0 A0 E3   MOV    R12, #7
__text:00002920 00 00 40 E3   MOVT   R0, #0
__text:00002924 04 20 A0 E3   MOV    R2, #4
__text:00002928 00 00 8F E0   ADD    R0, PC, R0
__text:0000292C 06 30 A0 E3   MOV    R3, #6
__text:00002930 05 10 A0 E3   MOV    R1, #5
__text:00002934 00 20 8D E5   STR    R2, [SP,#0x1C+var_1C]
__text:00002938 0A 10 8D E9   STMFA  SP, {R1,R3,R12}
__text:0000293C 08 90 A0 E3   MOV    R9, #8
__text:00002940 01 10 A0 E3   MOV    R1, #1
__text:00002944 02 20 A0 E3   MOV    R2, #2
__text:00002948 03 30 A0 E3   MOV    R3, #3
__text:0000294C 10 90 8D E5   STR    R9, [SP,#0x1C+var_C]
__text:00002950 A4 05 00 EB   BL     _printf
__text:00002954 07 D0 A0 E1   MOV    SP, R7
__text:00002958 80 80 BD E8   LDMFD  SP!, {R7,PC}
\end{lstlisting}

\myindex{ARM!\Instructions!STMFA}
\myindex{ARM!\Instructions!STMIB}
Presque la même chose que ce que nous avons déjà vu, avec l'exception de l'instruction
\INS{STMFA} (Store Multiple Full Ascending), qui est un synonyme de l'instruction
\INS{STMIB} (Store Multiple Increment Before).
Cette instruction incrémente la valeur du registre \ac{SP} et écrit seulement
après la valeur registre suivant dans la mémoire, plutôt que d'effectuer ces
deux actions dans l'ordre inverse.

Une autre chose qui accroche le regard est que les instructions semblent être arrangées
de manière aléatoire.
Par exemple, la valeur dans le registre \Reg{0} est manipulée en trois endroits,
aux adresses \GTT{0x2918}, \GTT{0x2920} et \GTT{0x2928}, alors qu'il serait possible
de le faire en un seul endroit.

Toutefois, le compilateur qui optimise doit avoir ses propres raisons d'ordonner
les instructions pour avoir une plus grande éfficacité à l'exécution.

D'habitude, le processeur essaye d'exécuter simultanément des instructions situées côte à côte.\\
Par exemple, des instructions comme \INS{MOVT R0, \#0} et \INS{ADD R0, PC, R0} ne
peuvent pas être exécutées simultanément puisqu'elles modifient toutes deux le
registre \Reg{0}.
D'un autre côté, les instructions \INS{MOVT R0, \#0} et \INS{MOV R2, \#4} peuvent
être exécutées simlutanément puisque leurs effets n'interfèrent pas l'un avec l'autre
lors de leurs exécution.
Probablement que le compilateur essaye de générer du code arrangé de cette façon
(lorsque c'est possible).

\myparagraph{\OptimizingXcodeIV: \ThumbTwoMode}

\begin{lstlisting}[style=customasmARM]
__text:00002BA0               _printf_main2
__text:00002BA0
__text:00002BA0               var_1C = -0x1C
__text:00002BA0               var_18 = -0x18
__text:00002BA0               var_C  = -0xC
__text:00002BA0
__text:00002BA0 80 B5          PUSH     {R7,LR}
__text:00002BA2 6F 46          MOV      R7, SP
__text:00002BA4 85 B0          SUB      SP, SP, #0x14
__text:00002BA6 41 F2 D8 20    MOVW     R0, #0x12D8
__text:00002BAA 4F F0 07 0C    MOV.W    R12, #7
__text:00002BAE C0 F2 00 00    MOVT.W   R0, #0
__text:00002BB2 04 22          MOVS     R2, #4
__text:00002BB4 78 44          ADD      R0, PC  ; char *
__text:00002BB6 06 23          MOVS     R3, #6
__text:00002BB8 05 21          MOVS     R1, #5
__text:00002BBA 0D F1 04 0E    ADD.W    LR, SP, #0x1C+var_18
__text:00002BBE 00 92          STR      R2, [SP,#0x1C+var_1C]
__text:00002BC0 4F F0 08 09    MOV.W    R9, #8
__text:00002BC4 8E E8 0A 10    STMIA.W  LR, {R1,R3,R12}
__text:00002BC8 01 21          MOVS     R1, #1
__text:00002BCA 02 22          MOVS     R2, #2
__text:00002BCC 03 23          MOVS     R3, #3
__text:00002BCE CD F8 10 90    STR.W    R9, [SP,#0x1C+var_C]
__text:00002BD2 01 F0 0A EA    BLX      _printf
__text:00002BD6 05 B0          ADD      SP, SP, #0x14
__text:00002BD8 80 BD          POP      {R7,PC}
\end{lstlisting}

La sortie est presque la même que dans l'exemple précédent, avec l'exception que
des instructions Thumb sont utilisées à la place.
% FIXME: also STMIA is used instead of STMIB,
% which is why it uses LR, which is 4 bytes ahead of SP

\myparagraph{ARM64}

\mysubparagraph{GCC (Linaro) 4.9 \NonOptimizing}

\lstinputlisting[caption=GCC (Linaro) 4.9 \NonOptimizing,style=customasmARM]{patterns/03_printf/ARM/ARM8_O0_FR.lst}

Les 8 premiers arguments sont passés dans des registres X- ou W-: \ARMPCS.
Un pointeur de chaîne nécessite un registre 64-bit, donc il est passé dans \RegX{0}.
Toutes les autres valeurs ont un type \Tint 32-bit, donc elles sont stockées dans
la partie 32-bit des registres (W-).
Le 9ème argument (8) est passé par la pile.
En effet: il m'est pas possible de passer un grand nombre d'arguments par les registres,
car le nombre de registres est limité.

GCC (Linaro) 4.9 \Optimizing génère le même code.
